///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////

package ru.goodcore.resource
{

import ru.goodcore.net.URI;
import ru.goodcore.resource.errors.ResourceBundleError;
	


/**
 * 
 * @author					Dimarik
 * @version					1.0
 * @playerversion			Flash 9
 * @langversion				3.0
 *
 * @keyword					
 */
public class ResourceBundle
{

	include "../../../includes/core/Version.as";

	//-------------------------------------------------------------------------
	//
	//  Public class's constants
	//
	//-------------------------------------------------------------------------

	//-------------------------------------------------------------------------
	//
	//  Class properties
	//
	//-------------------------------------------------------------------------

	//-------------------------------------------------------------------------
	//
	//  Class variables
	//
	//-------------------------------------------------------------------------

	/**
	 * @private 
	 */
	private static var _bundlesStorage:		Object = new Object();

	//-------------------------------------------------------------------------
	//
	//  Class methods
	//
	//-------------------------------------------------------------------------

	/**
	 * Gets a resource bundle using the specified base name and locale.
	 * 
	 * @param name
	 * @param locale
	 * @return resourceBundle
	 * 
	 */
	public static function getBundle(name:String, locale:Locale = null):ResourceBundle {
		if ( !name )
			throw new ResourceBundleError(ResourceBundleError.INVALID_BUNDLE_NAME);

		if ( !locale )
			locale = Locale.defaultLocale;

		var localeId:	String = locale.toString();
		var bundles:	Object = _bundlesStorage[localeId];

		if ( !bundles )
			bundles = _bundlesStorage[localeId] = new Object();

		var bundle:	ResourceBundle = bundles[name];

		if ( !bundle )
			_bundlesStorage[name] = bundle = new ResourceBundle(name);

		return bundle;
	}

	//-------------------------------------------------------------------------
	//
	//  Private class variables
	//
	//-------------------------------------------------------------------------

	//-------------------------------------------------------------------------
	//
	//  Constructor
	//
	//-------------------------------------------------------------------------

	/**
	 * Constructor
	 */
	public function ResourceBundle(name:String) {
		super();
		if ( !name )
			throw new ResourceBundleError(ResourceBundleError.INVALID_BUNDLE_NAME);

		this._name = name;
	}

	//-------------------------------------------------------------------------
	//
	//  Properties
	//
	//-------------------------------------------------------------------------

	//-------------------------------------
	//  name
	//-------------------------------------
	/**
	 * @private
	 */
	private var _name:	String;

	public function get name():String {
		return this._name;
	}

	//-------------------------------------
	//  locale
	//-------------------------------------
	/**
	 * @private
	 */
	private var _locale:	Locale;

	/**
	 * Returns the locale of this resource bundle.
	 * 
	 * @return the locale of this resource bundle.
	 */ 
	public function get locale():Locale {
		return this._locale;
	}

	//-------------------------------------
	//  parent
	//-------------------------------------
	/**
	 * @private
	 */
	private var _parent:	ResourceBundle;

	/**
	 * The parent bundle of this bundle.
	 * @return parent bundle
	 * 
	 */
	public function get parent():ResourceBundle {
		return this._parent;
	}

	public function set parent(value:ResourceBundle):void {
		if (this._parent == value) return;
		this._parent = value;
	}

	/**
	 * Check the bundle is empty
	 * 
	 * @return true if this resource bundle is empty
	 */
	public function get empty():Boolean {
		for ( var name:String in this._hash ) {
			return false;
		}
		return true;
	}

	//-------------------------------------------------------------------------
	//
	//  Private variables
	//
	//-------------------------------------------------------------------------

	/**
	 * @private
	 * Resource storage 
	 */	
	private const _hash:	Object = new Object();

	//-------------------------------------------------------------------------
	//
	//  Public methods
	//
	//-------------------------------------------------------------------------

	/**
	 * Adds resource
	 * 
	 * @param key key string
	 * @param value value object
	 * 
	 */
	public function addResource(key:String, value:*):void {
		if ( !key )
			throw new ResourceBundleError(ResourceBundleError.INVALID_BUNDLE_NAME);
		this._hash[key] = value;
	}

	/**
	 * Check resource in this resource bundle
	 * 
	 * @param key resource name
	 * @return true if resource exist in this resource bundle
	 * 
	 */
	public function hasObject(key:String):Boolean {
		if ( !key )
			throw new ResourceBundleError(ResourceBundleError.INVALID_BUNDLE_NAME);
		return key in this._hash;
	}

	/**
	 * Gets an object for the given key from this resource bundle or one of its parents.
	 *  
	 * @param key
	 * @return string
	 */
	public function getObject(key:String):* {
		var o:* = this._hash[key];

		if ( !o && this._parent ) {
			o = this._parent.getObject(key);
		}

		if ( !o )
			throw new ResourceBundleError(ResourceBundleError.MISSING_RESOURCE, key);

		return o;
	}

	/**
	 * Gets a string for the given key from this resource bundle or one of its parents.
	 *  
	 * @param key
	 * @return string
	 */
	public function getString(key:String):String {
		return this.getObject(key) as String;
	}


	//[ArrayElementType('String')]
	/**
	 * Gets a string array for the given key from this resource bundle or one of its parents.
	 *  
	 * @param key The name of param
	 * @return array of strings
	 */
	public function getStringArray(key:String):Array {
		return this.getObject(key) as Array;
	}

	[ArrayElementType('Object')]
	/**
	 * Returns all resources as array
	 * 
	 * @return all resources as array
	 */
	public function getResources():Array {
		var result:Array = new Array();
		for ( var name:String in this._hash ) {
			result.push( name );
		}
		return result;
	}

	//-------------------------------------------------------------------------
	//
	//  Protected methods
	//
	//-------------------------------------------------------------------------

	//-------------------------------------------------------------------------
	//
	//  Private methods
	//
	//-------------------------------------------------------------------------


}
}